const Utils = {
	/**
	 * 获取数据类型
	 * @param data
	 * @returns
	 */
	getType(data: any): string {
		return {}.toString.call(data).slice(8, -1).toLowerCase();
	},

	/**
	 * 数据可选链获取
	 * @param {*} data 数据源
	 * @param {string|array} path 路径
	 * @param {*} defaultValue  默认值，取不到值得时候用
	 */
	dGet(
		data: any,
		path: (string | number[]) | string,
		defaultValue?: any,
	): any {
		const pathList = typeof path === 'string' ? path.split('.') : path;
		let result = data;
		try {
			while (pathList.length) {
				const key = pathList.shift() || '';
				result = result.hasOwnProperty(key)
					? result[key]
					: defaultValue;
			}
			return result;
		} catch (err) {
			return defaultValue;
		}
	},

	/**
	 * 是否为json
	 * @param data
	 * @returns
	 */
	isJson(data: any): boolean {
		try {
			let d = JSON.parse(data);
			return Utils.getType(d) === 'object';
		} catch (e) {}
		return false;
	},

	/**
	 * 转为下划线
	 * @param {String} string
	 * @returns
	 */
	stringUnderline(str: string): string {
		let temp = str.replace(/[A-Z]/g, function (i) {
			return '_' + i.toLowerCase();
		});
		if (temp.slice(0, 1) === '_') {
			temp = temp.slice(1); //如果首字母是大写，执行replace时会多一个_，需要去掉
		}
		return temp;
	},

	/**
	 * 封装foreach
	 * @param {*} source
	 * @param {*} callback
	 * @param {boolean} allOwnKeys 是否包含原型属性
	 * @returns
	 */
	forEach(
		source: any[] | object,
		callback: (val: any, key: string | number) => void,
		{ allOwnKeys = false } = {},
	) {
		if (source === undefined || source === null) return;
		if (typeof source !== 'object') {
			source = [source];
		}
		if (Array.isArray(source)) {
			for (let i = 0, len = source.length; i < len; i++) {
				callback.call(null, source[i], i);
			}
		} else {
			const keys = allOwnKeys
				? Object.getOwnPropertyNames(source)
				: Object.keys(source);
			let key = '';
			for (let i = 0, len = keys.length; i < len; i++) {
				key = keys[i];
				// @ts-ignore
				callback.call(null, source[key], key);
			}
		}
		return source;
	},

	/**
	 * 序列化数据
	 */
	parseData(data: any): any {
		try {
			if (!data) return data;
			return Utils.isJson(data) ? JSON.parse(data) : data;
		} catch (error) {
			return null;
		}
	},
};

export default Utils;
